fix: enforce workdir confinement in LocalFileManagerDriver to prevent path traversal#2195
Open
Joshua-Medvinsky wants to merge 1 commit into
Conversation
… path traversal _full_path() bypassed the workdir for absolute paths (os.path.isabs check returned the path unchanged) and had no boundary check after normpath resolved '..' sequences. Both vectors allowed reading/writing arbitrary files on the host filesystem. This change: - Removes the isabs short-circuit; every path is joined with workdir (stripping a leading '/' so os.path.join doesn't discard the base). - Adds a realpath-based boundary check: if the resolved path falls outside workdir_real, a ValueError is raised before any I/O is attempted. Signed-off-by: FailSafe Researcher <joshua@getfailsafe.com>
|
Hi maintainers 👋 This vulnerability was found by FailSafe — a top agentic cybersecurity company specializing in automated deep security analysis of AI/ML and agentic codebases. We're reporting these initial findings as a social good contribution to help secure the open-source AI ecosystem. If you'd like us to perform a deeper, more comprehensive security scan of your project, we'd love to hear from you — reach out at joshua@getfailsafe.com. Thanks for maintaining this project! 🙏 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LocalFileManagerDriver._full_path()(griptape/drivers/file_manager/local_file_manager_driver.py:52) contains two path traversal vectors that allow an AI agent to read or write arbitrary files outside the configuredworkdir:Vector 1 — Absolute path bypass:
If
path = "/etc/passwd",os.path.isabs()returns True andfull_path = "/etc/passwd"— the workdir is completely skipped.Vector 2 —
..traversal via normpath:../../../etc/passwdis not absolute, so it joins with workdir:/workdir/../../../etc/passwd.os.path.normpath()then resolves..sequences, producing/etc/passwd— outside the workdir with no boundary check.Exploit scenario: An adversarial document processed by a griptape agent can use prompt injection to instruct the LLM to call
FileManagerTool.load_files_from_diskwith a traversal path, leaking SSH private keys,.envfiles, AWS credentials, or other sensitive files.Confirmed by test:
Severity: High (CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N — 8.7)
Fix
Remove the
isabsshort-circuit so all paths go throughos.path.join(workdir, path.lstrip('/')), then add arealpath-based boundary check:Test Plan
_full_path("/etc/passwd")raisesValueError(was: returned/etc/passwd)_full_path("../../../etc/passwd")raisesValueError(was: returned/etc/passwd)_full_path("uploads/file.txt")returns<workdir>/uploads/file.txt(no regression)_full_path("subdir/")returns<workdir>/subdir/with trailing slash preservedSecurity Note
Severity: High. Exploitable via prompt injection in any griptape agent that uses
FileManagerToolwithLocalFileManagerDriver(the default). Filed via GitHub Private Vulnerability Reporting.